﻿#include "FITKAbaqusHDF5AdaptorBoundary.h"
#include "FITK_Kernel/FITKCore/FITKEnumTransformer.hpp"

#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Reader.h"
#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Writer.h"

#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractBoundaryCondition.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionSymmetry.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionDisplacement.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionVelocity.h"

#include "FITK_Component/FITKAbaqusData/FITKDataCase.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaStepManager.h"

namespace IO
{
    QString FITKAbaqusHDF5AdaptorBoundary::getAdaptorClass()
    {
        return "FITKAbaqusHDF5AdaptorBoundaryCondition";
    }

    void FITKAbaqusHDF5AdaptorBoundary::setDataCase(AbaqusData::FITKDataCase* caseData)
    {
        _caseData = caseData;
    }

    bool FITKAbaqusHDF5AdaptorBoundary::adaptR()
    {
        auto boundaryCondition = dynamic_cast<Interface::FITKAbaAbstractBoundaryCondition*>(_dataObj);
        if (!_reader || !_h5Group || !boundaryCondition || !_caseData) return false;
        bool isR = true;
        isR &= readBoundaryCondition(boundaryCondition, *_h5Group);
        return isR;
    }

    bool FITKAbaqusHDF5AdaptorBoundary::adaptW()
    {
        auto boundaryCondition = dynamic_cast<Interface::FITKAbaAbstractBoundaryCondition*>(_dataObj);
        if (!_writer || !_h5Group || !boundaryCondition || !_caseData) return false;
        bool isW = true;
        isW &= writeBoundaryCondition(boundaryCondition, *_h5Group);
        return isW;
    }

    bool FITKAbaqusHDF5AdaptorBoundary::readBoundaryCondition(Interface::FITKAbaAbstractBoundaryCondition * bc, H5::Group & h5Group)
    {
        if (!bc) return false;
        bool isR = true;
        //FITKBoundaryLocation
        isR &= readBoundaryLocation(bc, h5Group);

        bool ActiveState = readBoolAttribute(h5Group, "ActiveState");
        bc->setActiveState(ActiveState);

        auto stepManager = _caseData->getStepManager();
        int stepCount = stepManager->getDataCount();
        for (int i = 0; i < stepCount; ++i)
        {
            auto step = stepManager->getDataByIndex(i);
            int stepID = step->getDataObjectID();
            if (!h5Group.nameExists(std::to_string(stepID))) return false;
            auto stepGroup = h5Group.openGroup(std::to_string(stepID));

            //FITKAbaStepRelatedDataObject
            int CreatedStep = readIntAttribute(stepGroup, "CreatedStep");
            int DeactiveStep = readIntAttribute(stepGroup, "DeactiveStep");
            bc->setCreatedStep(CreatedStep);
            bc->setDeactiveStep(DeactiveStep);

            auto BoundaryConditionType = bc->getBoundaryConditionType();
            if (BoundaryConditionType == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::DisplacementRotation)
            {
                isR &= readDisplacement(bc, stepID, stepGroup);
            }
            else if (BoundaryConditionType == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::SymmetryAntisymmetryEncastre)
            {
                isR &= readSymmetry(bc, stepID, stepGroup);
            }
        }
        return isR;
    }

    bool FITKAbaqusHDF5AdaptorBoundary::readDisplacement(Interface::FITKAbaAbstractBoundaryCondition* bc, int stepID, H5::Group& h5Group)
    {
        auto boundaryCondition = dynamic_cast<Interface::FITKAbaBoundaryConditionDisplacement*>(bc);
        if (!boundaryCondition) return false;

        int CsysID = readIntAttribute(h5Group, "CsysID");
        boundaryCondition->setCsysId(CsysID);

        int AnalyticalFieldId = readIntAttribute(h5Group, "AnalyticalFieldId");
        boundaryCondition->setAnalyticalFieldId(AnalyticalFieldId);

        bool U1State = readBoolAttribute(h5Group, "U1State");
        boundaryCondition->setU1State(U1State, stepID);
        bool U2State = readBoolAttribute(h5Group, "U2State");
        boundaryCondition->setU2State(U2State, stepID);
        bool U3State = readBoolAttribute(h5Group, "U3State");
        boundaryCondition->setU3State(U3State, stepID);
        bool UR1State = readBoolAttribute(h5Group, "UR1State");
        boundaryCondition->setUR1State(UR1State, stepID);
        bool UR2State = readBoolAttribute(h5Group, "UR2State");
        boundaryCondition->setUR2State(UR2State, stepID);
        bool UR3State = readBoolAttribute(h5Group, "UR3State");
        boundaryCondition->setUR3State(UR3State, stepID);
        double U1 = readDoubleAttribute(h5Group, "U1");
        boundaryCondition->setU1(U1, stepID);
        double U2 = readDoubleAttribute(h5Group, "U2");
        boundaryCondition->setU2(U2, stepID);
        double U3 = readDoubleAttribute(h5Group, "U3");
        boundaryCondition->setU3(U3, stepID);
        double UR1 = readDoubleAttribute(h5Group, "UR1");
        boundaryCondition->setUR1(UR1, stepID);
        double UR2 = readDoubleAttribute(h5Group, "UR2");
        boundaryCondition->setUR2(UR2, stepID);
        double UR3 = readDoubleAttribute(h5Group, "UR3");
        boundaryCondition->setUR3(UR3, stepID);
        int AmplitudeId = readIntAttribute(h5Group, "AmplitudeId");
        boundaryCondition->setAmplitudeId(AmplitudeId);
        return true;
    }

    bool FITKAbaqusHDF5AdaptorBoundary::readSymmetry(Interface::FITKAbaAbstractBoundaryCondition* bc, int stepID, H5::Group& h5Group)
    {
        auto boundaryCondition = dynamic_cast<Interface::FITKAbaBoundaryConditionSymmetry*>(bc);
        if (!boundaryCondition) return false;
        bool isR = true;

        if (!h5Group.attrExists("SymmetryAntisymmetryEncastreType")) return false;
        auto strType = readStrAttribute(h5Group, "SymmetryAntisymmetryEncastreType");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::AbaSymmetryAntisymmetryEncastreType::SymmetryAntisymmetryEncastreType> fitkTypeTrafer;
        bool isValid = false;
        auto eType = fitkTypeTrafer.fromString(QString::fromStdString(strType), isValid);
        if (!isValid) return false;
        boundaryCondition->setType(eType);

        int CsysID = readIntAttribute(h5Group, "CsysID");
        boundaryCondition->setCsysId(CsysID);
        return isR;
    }

    bool FITKAbaqusHDF5AdaptorBoundary::readVelocity(Interface::FITKAbaAbstractBoundaryCondition* bc, int stepID, H5::Group& h5Group)
    {
        auto boundaryCondition = dynamic_cast<Interface::FITKAbaBoundaryConditionVelocity*>(bc);
        if (!boundaryCondition) return false;
        return readDisplacement(boundaryCondition, stepID, h5Group);
    }


    bool FITKAbaqusHDF5AdaptorBoundary::writeBoundaryCondition(Interface::FITKAbaAbstractBoundaryCondition * bc, H5::Group & h5Group)
    {
        if (!bc) return false;
        bool isW = true;
        bool isValid = false;

        std::string groupName = createParentAttribute(bc, h5Group);
        if (groupName.empty())return false;

        _h5CreateGroup = h5Group.createGroup(groupName);
        auto BoundaryConditionType = bc->getBoundaryConditionType();
        //写出模型信息
        isW &= writeBoundaryLocation(bc, _h5CreateGroup);
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType> fitkBCTypeTrafer;
        auto sType = fitkBCTypeTrafer.toStrting(BoundaryConditionType, isValid);
        if (!isValid) return false;
        writeStrAttribute(_h5CreateGroup, "Type", sType.toStdString());

        bool ActiveState = bc->getActiveState();
        writeBoolAttribute(_h5CreateGroup, "ActiveState", &ActiveState);

        auto stepManager = _caseData->getStepManager();
        int stepCount = stepManager->getDataCount();
        for (int i = 0; i < stepCount; ++i)
        {
            auto step = stepManager->getDataByIndex(i);
            int stepID = step->getDataObjectID();
            auto stepGroup = _h5CreateGroup.createGroup(std::to_string(stepID));
            //FITKAbaStepRelatedDataObject
            int CreatedStep = bc->getCreatedStep();
            writeIntAttribute(stepGroup, "CreatedStep", &CreatedStep);
            int DeactiveStep = bc->getDeactiveStep();
            writeIntAttribute(stepGroup, "DeactiveStep", &DeactiveStep);

            if (BoundaryConditionType == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::DisplacementRotation)
            {
                isW &= writeDisplacement(bc, stepID, stepGroup);
            }
            else if (BoundaryConditionType == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::SymmetryAntisymmetryEncastre)
            {
                isW &= writeSymmetry(bc, stepID, stepGroup);
            }
            else if (BoundaryConditionType == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::VelocityAngularVelocity)
            {
                isW &= writeVelocity(bc, stepID, stepGroup);
            }
        }
        return isW;
    }


    bool FITKAbaqusHDF5AdaptorBoundary::writeDisplacement(Interface::FITKAbaAbstractBoundaryCondition* bc, int stepID, H5::Group& h5Group)
    {
        auto boundaryCondition = dynamic_cast<Interface::FITKAbaBoundaryConditionDisplacement*>(bc);

        int CsysID = boundaryCondition->getCsysId();
        writeIntAttribute(h5Group, "CsysID", &CsysID);

        int AnalyticalFieldId = boundaryCondition->getAnalyticalFieldId();
        writeIntAttribute(h5Group, "AnalyticalFieldId", &AnalyticalFieldId);

        bool U1State = boundaryCondition->getU1State(stepID);
        writeBoolAttribute(h5Group, "U1State", &U1State);
        bool U2State = boundaryCondition->getU2State(stepID);
        writeBoolAttribute(h5Group, "U2State", &U2State);
        bool U3State = boundaryCondition->getU3State(stepID);
        writeBoolAttribute(h5Group, "U3State", &U3State);
        bool UR1State = boundaryCondition->getUR1State(stepID);
        writeBoolAttribute(h5Group, "UR1State", &UR1State);
        bool UR2State = boundaryCondition->getUR2State(stepID);
        writeBoolAttribute(h5Group, "UR2State", &UR2State);
        bool UR3State = boundaryCondition->getUR3State(stepID);
        writeBoolAttribute(h5Group, "UR3State", &UR3State);
        double U1 = boundaryCondition->getU1(stepID);
        writeDoubleAttribute(h5Group, "U1", &U1);
        double U2 = boundaryCondition->getU2(stepID);
        writeDoubleAttribute(h5Group, "U2", &U2);
        double U3 = boundaryCondition->getU3(stepID);
        writeDoubleAttribute(h5Group, "U3", &U3);
        double UR1 = boundaryCondition->getUR1(stepID);
        writeDoubleAttribute(h5Group, "UR1", &UR1);
        double UR2 = boundaryCondition->getUR2(stepID);
        writeDoubleAttribute(h5Group, "UR2", &UR2);
        double UR3 = boundaryCondition->getUR3(stepID);
        writeDoubleAttribute(h5Group, "UR3", &UR3);
        int AmplitudeId = boundaryCondition->getAmplitudeId(stepID);
        writeIntAttribute(h5Group, "AmplitudeId", &AmplitudeId);
        return true;
    }

    bool FITKAbaqusHDF5AdaptorBoundary::writeSymmetry(Interface::FITKAbaAbstractBoundaryCondition* bc, int stepID, H5::Group& h5Group)
    {
        auto boundaryCondition = dynamic_cast<Interface::FITKAbaBoundaryConditionSymmetry*>(bc);
        if (!boundaryCondition) return false;
        bool isW = true;
        bool isValid = false;

        auto eSymmetryAntisymmetryEncastreType = boundaryCondition->getType();
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::AbaSymmetryAntisymmetryEncastreType::SymmetryAntisymmetryEncastreType> fitkBCTypeTrafer;
        auto sSymmetryAntisymmetryEncastreType = fitkBCTypeTrafer.toStrting(eSymmetryAntisymmetryEncastreType, isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "SymmetryAntisymmetryEncastreType", sSymmetryAntisymmetryEncastreType.toStdString());

        int CsysID = boundaryCondition->getCsysId();
        writeIntAttribute(h5Group, "CsysID", &CsysID);

        return isW;
    }

    bool FITKAbaqusHDF5AdaptorBoundary::writeVelocity(Interface::FITKAbaAbstractBoundaryCondition* bc, int stepID, H5::Group& h5Group)
    {
        auto boundaryCondition = dynamic_cast<Interface::FITKAbaBoundaryConditionVelocity*>(bc);
        if (!boundaryCondition) return false;
        return writeDisplacement(boundaryCondition, stepID, h5Group);
    }

}